#include "header.h"
#include "./dma/dma.h"
#include "./mpu/mpu.h"
#include "./bluetooth/bluetooth_usart.h"
#include "./bluetooth/bluetooth_at.h"
#include "./mobile_net/mobile_net.h"
#include "./gps/gps.h"
#include "./wifi/wifi.h"
#include "./screen/oled.h"
#include "./flash/flash.h"
#include "./mqtt/mqtt.h"
#include "./log/log.h"
#include "./delay/delay.h"
#include <stdlib.h>

/*
 *默认复用：
 *USART1:上位机串口和蓝牙串口,TX:PA9,RX:PA10
 *USART2:WIFI串口, TX:PA2, RX:PA3
 *USART3:GPS串口, TX:PB10, RX:PB11
 *重定义复用：
 *USART1:蓝牙串口,TX:PB6,RX:PB7
 */

// extern variables(外部变量)
extern USARTBuffer bluetoothInfo;
extern USARTBuffer usart_buffer;
extern USARTBuffer gpsUSARTBuffer;
extern USARTBuffer wifi_usart_buffer;
extern _SaveData Save_Data;
extern uint8_t AtRxBuffer[512];

extern uint8_t boolATFlag;		// 蓝牙AT模式标志位
uint8_t boolGPSOpenFlag;		// GPS模块是否打开标志位
uint8_t boolMPUOpenFlag;		// MPU是否打开标志位
uint8_t len;					// MQTT构建包内容以及长度
uint8_t json_len;				// 构建JSON数据包
uint8_t MID;					// 定义用于存放MID号的变量
uint16_t DID;					// 定义用于存放DID号的变量
uint8_t flash_max_read_length;	// flash最大读取长度
uint8_t flash_max_write_length; // flash最大写入长度
uint8_t ID;						// 定义用于存放ID号的变量
int16_t AX, AY, AZ, GX, GY, GZ; // 定义用于存放各个数据的变量

uint32_t desBluetoothData[USART_RX_Buffer_Length]; // 蓝牙串口接收数据DMA缓冲区
uint32_t desUSARTData[USART_RX_Buffer_Length];	   // USART接收数据DMA缓冲区
uint32_t desGPSData[USART_RX_Buffer_Length];	   // GPS接收数据DMA缓冲区
uint8_t dev_id[20];								   // 设备ID
uint8_t mqtt_msg[300];							   // MQTT数据包
uint8_t t_payload[200];							   // MQTT数据包内容
float gpsFloatdata[2];							   // GPS数据

uint8_t USART2_RX_STA = 0; // 接收状态标记
char Rcv_Str[1024];		   // 接收缓冲区
char USART2_RX_BUF[1024];  // 接收缓冲区
uint8_t personMode;		   // 0:正常模式，1:危险模式

// project entry function(项目入口函数)
int main(void)
{
	variateInit();		   // 变量初始化
	MPUInit();			   // MPU初始化(I2C)
	flashInit(1024, 1024); // flash初始化(SPI)
	OLED_Init();		   // OLED初始化(SPI)
	Bluetooth_Init(9600);  // 蓝牙串口
	TestUASRT_Init(9600);  // 上位机串口
	GPS_USART_Init(9600);  // GPS串口
	WIFI_USART_Init(9600); // WIFI串口
	MqttOnenet_Init();	   // MQTT初始化
	clrStruct();		   // 清空GPS数据结构体
	// DMA Init(初始化DMA)
	USART_DMA_Init(DMA1_Channel1, (uint32_t)bluetoothInfo.USART_RX_Buffer, desBluetoothData, USART_RX_Buffer_Length);

	while (1)
	{
		BluetoothToComputer();
		deposeComputerData();
		if (boolGPSOpenFlag)
		{
			initlizateGPSData(); // 分析GPS数据
		}
		if (boolMPUOpenFlag)
		{
			MPUGet();
		}
		connectServer();
		char *tmpStr = NULL;
		if (Rcv_Str != NULL)
		{
			tmpStr = jsonDataDepose(Rcv_Str);
		}
		if (judeModeFlag(tmpStr))
		{
			OLED_ShowString(0, 0, "Warning!!!!!");
			int waitTime = 100000;
			while (waitTime--)
			{
				mqttStringSend();
				delay_ms(100);
				extern int onenetdata_len;
				if (onenetdata_len)
					break;
			}
			waitTime = 100000;
			gpsFloatdata[0] = 'w' - '0';
			gpsFloatdata[1] = 'w' - '0';
			while (waitTime--)
			{
				mqttStringSend();
				delay_ms(100);
				extern int onenetdata_len;
				if (onenetdata_len)
					break;
			}
			OLED_ShowString(0, 0, "Send Warning Info");
			delay_ms(100);
		}
		else
		{
			OLED_ShowString(0, 0, "Normal Mode");
		}
		mqttStringSend();
	}
}

// MPU初始化
void MPUInit(void)
{
	MPU6050_Init();		  // MPU6050初始化
	ID = MPU6050_GetID(); // 获取MPU6050的ID号
}

// MPU获取数据
void MPUGet(void)
{
	MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ); // 获取MPU6050的数据
}

// 处理MPU数据
void deposeMpuData(void)
{
}

// flash 初始化
void flashInit(uint8_t readLength, uint8_t writeLength)
{
	flash_max_read_length = readLength;	  // flash最大读取长度
	flash_max_write_length = writeLength; // flash最大写入长度
	W25Q64_Init();						  // W25Q64初始化
	W25Q64_ReadID(&MID, &DID);			  // 获取W25Q64的ID号
}

// 扇区擦除
void flashClear(void)
{
	W25Q64_SectorErase(0x000000);
}

// 读取刚写入的测试数据到读取数据的测试数组中
void flashRead(uint8_t *data, uint16_t len)
{
	W25Q64_ReadData(0x000000, data, len);
}

// 将写入数据的测试数组写入到W25Q64中
void flashWrite(uint8_t *data, uint16_t len)
{
	W25Q64_PageProgram(0x000000, data, len);
}

// 定义一个函数，用于将GPS数据从字符串转换为浮点数
void gpsDataChange(void)
{
	// 将Save_Data结构体中的longitude字段（字符串类型）转换为浮点数，并存储在gpsFloatdata数组的第一个元素中
	gpsFloatdata[0] = atof(Save_Data.longitude);
	// 将Save_Data结构体中的latitude字段（字符串类型）转换为浮点数，并存储在gpsFloatdata数组的第二个元素中
	gpsFloatdata[1] = atof(Save_Data.latitude);
}

void mqttStringSend(void)
{
	memset(t_payload, 0, 200); // 清空t_payload数组
	memset(mqtt_msg, 0, 300);  // 清空mqtt_msg数组
	USART_SendString(USART1, "发送数据到ONENET服务器...\r\n");
	gpsDataChange(); // GPS数据转换
	if (gpsFloatdata[0] == 0 || gpsFloatdata[1] == 0)
		json_len = MqttOnenet_Savedata(t_payload, 116.402544, 39.915599); // 构建JSON数据，ONENET要求提交json数据。防止发送空数据
	else
		json_len = MqttOnenet_Savedata(t_payload, gpsFloatdata[0], gpsFloatdata[1]);   // 构建JSON数据，ONENET要求提交json数据。
	len = mqtt_onenetpublish_message(mqtt_msg, "$dp", (char *)t_payload, json_len, 1); // 构建MQTT发送数据包
	sendMQTTPkt((char *)mqtt_msg, len);
	Clear_Buffer();
	delay_ms(2000);
	MqttSample_RecvPkt();
	delay_ms(1000);
	Clear_Buffer();
}

void MqttOnenet_Init(void)
{
	char *strx = NULL;
	Send_HttpPkt(REG_PKT_HEAD, REG_PKT_BODY, (char *)dev_id);		   // 发送注册信息到ONENET，请求注册设备，注册成功会返回设备ID。
	MQTTCONNECTServer();											   // 关闭HTTP采用TCP的方式去连接ONENET
	len = mqtt_connect_message(mqtt_msg, (char *)dev_id, PROD_ID, SN); // 构建发送数据包登录ONENET数据请求
	Clear_Buffer();
	sendMQTTPkt((char *)mqtt_msg, len); // 发送登录请求数据没有清空模块反馈的数据
	Clear_Buffer();
	USART_SendString(USART1, "等待服务器反馈数据\r\n ");
	delay_ms(4000);
	MqttSample_RecvPkt(); // 服务器的数据返回，对数据进行解析 需要很长时间 不要清空接收缓冲
	delay_ms(4000);
	Clear_Buffer();
}

// 函数名称：variateInit
// 函数功能：初始化全局变量和数据缓冲区
// 函数名称：variateInit
// 函数功能：初始化全局变量和数据缓冲区
void variateInit(void)
{
	// 将desBluetoothData缓冲区的前USART_RX_Buffer_Length个字节设置为0
	memset(desBluetoothData, 0, USART_RX_Buffer_Length);
	// 将desUSARTData缓冲区的前USART_RX_Buffer_Length个字节设置为0
	memset(desUSARTData, 0, USART_RX_Buffer_Length);
	// 将desGPSData缓冲区的前USART_RX_Buffer_Length个字节设置为0
	memset(desGPSData, 0, USART_RX_Buffer_Length);
	// 将dev_id缓冲区的前20个字节设置为0
	memset(dev_id, 0, 20);
	// 将mqtt_msg缓冲区的前300个字节设置为0
	memset(mqtt_msg, 0, 300);
	// 将t_payload缓冲区的前200个字节设置为0
	memset(t_payload, 0, 200);
	// 将gpsFloatdata缓冲区的前2个字节设置为0
	memset(gpsFloatdata, 0, 2);
	// 将Rcv_Str缓冲区的前1024个字节设置为0
	memset(Rcv_Str, 0, 1024);
	// 将USART2_RX_BUF缓冲区的前1024个字节设置为0
	memset(USART2_RX_BUF, 0, 1024);
	// 将len变量初始化为0
	len = 0;
	// 将json_len变量初始化为0
	json_len = 0;
	// 将boolATFlag变量初始化为0
	boolATFlag = 0;
	// 将boolGPSOpenFlag变量初始化为1
	boolGPSOpenFlag = 1;
	// 将USART2_RX_STA变量初始化为0
	USART2_RX_STA = 0;
	// 对personMode变量进行初始化，但未指定具体值
	personMode;
}

// Send Bluetooth data to USART(向上位机发送蓝牙数据)
// 函数定义：BluetoothToComputer
// 功能：当从蓝牙模块接收到数据时，将数据通过USART2发送到计算机
void BluetoothToComputer(void)
{
	// 检查是否接收到完整的蓝牙数据
	if (bluetoothInfo.USART_RX_Complete)
	{
		deposeBuletoothData(); // 处理蓝牙数据
		// 通过USART2发送接收到的蓝牙数据到计算机
		USART_SendString(USART2, bluetoothInfo.USART_RX_Buffer);
		// 重置接收完成标志，表示下一次接收尚未完成
		bluetoothInfo.USART_RX_Complete = 0;
		// 重置接收缓冲区的索引，准备下一次数据接收
		bluetoothInfo.USART_RX_Index = 0;
	}
}

void transferLetter(char *str, int index)
{
	int strSize = strlen(str);
	for (int i = 0; i < strSize; i++)
	{
		if (index)
		{
			// 全部大写
			if (str[i] >= 'a' && str[i] <= 'z')
			{
				str[i] -= 32;
			}
		}
		else
		{
			// 全部小写
			if (str[i] >= 'A' && str[i] <= 'Z')
			{
				str[i] += 32;
			}
		}
	}
}

void deposeBuletoothData(void)
{
	if (bluetoothInfo.USART_RX_Complete)
	{
		transferLetter(bluetoothInfo.USART_RX_Buffer, 0); // 转小写
		if (strstr(bluetoothInfo.USART_RX_Buffer, "close+gps") != NULL)
		{
			boolGPSOpenFlag = 0;
		}
		if (strstr(bluetoothInfo.USART_RX_Buffer, "open+gps") != NULL)
		{
			boolGPSOpenFlag = 1;
		}
		if (strstr(bluetoothInfo.USART_RX_Buffer, "close+mpu") != NULL)
		{
			boolGPSOpenFlag = 0;
		}
		if (strstr(bluetoothInfo.USART_RX_Buffer, "open+mpu") != NULL)
		{
			boolGPSOpenFlag = 1;
		}
		bluetoothInfo.USART_RX_Complete = 0;
		bluetoothInfo.USART_RX_Index = 0;
	}
}

// 函数名：deposeComputerData
// 功能：处理接收到的计算机数据，根据特定指令更新GPS开关标志
void deposeComputerData(void)
{
	// 检查USART接收是否完成
	if (usart_buffer.USART_RX_Complete)
	{
		// 检查接收缓冲区中是否包含"close+gps"字符串
		if (strstr(usart_buffer.USART_RX_Buffer, "close+gps") != NULL || strstr(usart_buffer.USART_RX_Buffer, "CLOSE+GPS") != NULL)
		{
			// 如果包含，则将GPS开关标志设置为关闭（0）
			boolGPSOpenFlag = 0;
		}
		// 检查接收缓冲区中是否包含"OPEN+GPS"字符串
		if (strstr(usart_buffer.USART_RX_Buffer, "open+gps") != NULL || strstr(usart_buffer.USART_RX_Buffer, "OPEN+GPS") != NULL)
		{
			// 如果包含，则将GPS开关标志设置为开启（1）
			boolGPSOpenFlag = 1;
		}
		// 重置USART接收完成标志，表示可以继续接收新的数据
		usart_buffer.USART_RX_Complete = 0;
		// 重置USART接收缓冲区索引，准备接收新的数据
		usart_buffer.USART_RX_Index = 0;
	}
}

// 分析GPS数据
// 定义一个函数，用于初始化GPS数据
void initlizateGPSData(void)
{
	// 调用parseGpsBuffer函数，解析GPS缓冲区中的数据
	parseGpsBuffer();
	// 调用printGpsBuffer函数，打印解析后的GPS数据
	printGpsBuffer();
}

void connectServer(void)
{
	// 测试ESP8266模块是否正常
	if (Send_Command("AT", "OK", 10))
	{
		USART_SendString(USART1, "ESP8266 Is Ready\r\n");
	}
	else
	{
		USART_SendString(USART1, "ESP8266 Not Ready\r\n");
	}
	// 如果WIFI不是Station模式，则设置为Station模式
	if (!Send_Command("AT+CWMODE_DEF?", "1", 20))
	{
		Send_Command("AT+CWMODE_DEF=1", "OK", 20);
	}
	// 查询WIFI是否连接，未连接则连接
	if (Send_Command("AT+CWJAP_DEF?", "No AP", 20))
	{
		delay_ms(500);
		Send_Command("AT+CWJAP_DEF=\"Xieyupei\",\"2468910\"", "OK", 50);
	}
	delay_ms(1000);
	TCP_Connect();					   // 建立TCP连接
	USART_SendString(USART1, Rcv_Str); // 打印网站返回的信息
	TCP_Disconnect();				   // 断开TCP连接
}

void buildWIFIConnect(char *dionet)
{
}

// 检测接收到的应答
uint8_t *Check_Command(char *str)
{
	char *strx = 0;
	if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) // 接收到一次数据了
	{
		USART2_RX_BUF[USART2_RX_STA & 0X7FFF] = 0; // 添加结束符
		strx = strstr((const char *)USART2_RX_BUF, (const char *)str);
	}
	return (uint8_t *)strx;
}

uint8_t Send_Command(char *cmd, char *ack, uint8_t waittime)
{
	uint8_t res = 1;
	USART2_RX_STA = 0;
	sprintf(cmd, "%s\r\n"); // 发送命令
	USART_SendString(USART2, cmd);
	if (ack && waittime) // 需要等待应答
	{
		while (--waittime) // 等待倒计时
		{
			delay_ms(10);
			if (USART2_RX_STA & 0X8000) // 接收到期待的应答结果
			{
				if (Check_Command(ack))
				{
					sprintf((uint8_t *)USART2_RX_BUF, "ack:%s\r\n");
					USART_SendString(USART1, USART2_RX_BUF);
					break; // 得到有效数据
				}
				USART2_RX_STA = 0;
			}
		}
		if (waittime == 0)
			res = 0;
	}
	return res;
}

// 向8266发送数据
void Send_Data(char *data)
{
	USART2_RX_STA = 0;
	sprintf(data, "%s"); // 发送数据
	USART_SendString(USART2, data);
}

// 建立TCP连接，并开启透传
void TCP_Connect(void)
{
	Send_Command("AT+CIPSTART=\"TCP\",\"https://cn.apihz.cn\",80", "OK", 50);
	delay_ms(500);
	// 查询是否成功建立连接，成功则开启透传发送数据
	if (Send_Command("AT+CIPSTATUS", "TCP", 20))
	{
		Send_Command("AT+CIPMODE=1", "OK", 20); // 设置为透传模式
		Send_Command("AT+CIPSEND", ">", 20);	// 开启透传
		delay_ms(1000);
		// 发送GET请求
		Send_Data("GET https://cn.apihz.cn/api/tianqi/dizhen.php\r\n");
		delay_ms(1000);
		strcpy(Rcv_Str, (const char *)USART2_RX_BUF); // 将接收到的返回数据复制
	}
}

// 退出透传，断开TCP连接
void TCP_Disconnect(void)
{
	// 退出发送模式
	while ((USART2->SR & 0X40) == 0)
		; // 等待发送空
	USART2->DR = '+';
	delay_ms(15); // 大于串口组帧时间(10ms)
	while ((USART2->SR & 0X40) == 0)
		; // 等待发送空
	USART2->DR = '+';
	delay_ms(15); // 大于串口组帧时间(10ms)
	while ((USART2->SR & 0X40) == 0)
		; // 等待发送空
	USART2->DR = '+';
	delay_ms(1000);						  // 等待1s
	while (!Send_Command("AT", "OK", 20)) // 退出透传判断.
	{
		delay_ms(200);
	}
	// 关闭透传模式
	Send_Command("AT+CIPMODE=0", "OK", 20);
	// 断开TCP连接
	Send_Command("AT+CIPCLOSE", "OK", 20);
}

char *jsonDataDepose(char *data)
{
	char *str = NULL;
	strcpy(str, data);
	return str;
}

uint8_t judeModeFlag(char *str)
{
	char *strx = NULL;
	strcpy(strx, str);
	return 0;
}